#include "stdafx.h"
#include "InputManager.h"

InputManager* InputManager::instance = NULL;

InputManager::InputManager() {
	m_observers = new std::list<InputObserver*>();	
}

InputManager::~InputManager() {
	delete m_observers;
	m_observers = NULL;

	Ogre::WindowEventUtilities::removeWindowEventListener(m_window, this);
	//Trigger shutdown sequence
	 windowClosed(m_window);
}

void InputManager::captureInput() {
	//Need to capture/update each device
    m_keyboard->capture();
    m_mouse->capture();
}
InputManager* InputManager::getInstance() {
  if (!instance) {
	 instance = new InputManager();
  }
  return instance;
}

void InputManager::registerObserver(InputObserver* observer) {
	m_observers->push_back(observer);
}

void InputManager::unregisterObserver(InputObserver* observer) {
	m_observers->remove(observer);
}

OIS::Mouse* InputManager::getMouse() {
	return m_mouse;
}

OIS::Keyboard* InputManager::getKeyboard() {
	return m_keyboard;
}

bool InputManager::keyPressed(const OIS::KeyEvent &arg) {
	std::list<InputObserver*>::iterator i;
	for(i=m_observers->begin(); i != m_observers->end(); ++i)  {
		if ((*i)->inputActive) {
			bool result = (*i)->keyPressed(arg);
			if(!result){
				return false;
			}
		}
	}
	return true;
}

bool InputManager::keyReleased(const OIS::KeyEvent &arg) {
	std::list<InputObserver*>::iterator i;
	for(i=m_observers->begin(); i != m_observers->end(); ++i) {
		if ((*i)->inputActive) {
			bool result = (*i)->keyReleased(arg);
			if(!result){
				return false;
			}
		}
	}
	return true;
}
	
bool InputManager::mouseMoved( const OIS::MouseEvent &arg ) {
	std::list<InputObserver*>::iterator i;
	for(i=m_observers->begin(); i != m_observers->end(); ++i)  {
		if ((*i)->inputActive) {
			bool result = (*i)->mouseMoved(arg);
			if(!result){
		    return false;
			}
		}
	}
	return true;
}

bool InputManager::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) {
	std::list<InputObserver*>::iterator i;
	for(i=m_observers->begin(); i != m_observers->end(); ++i) {
		if ((*i)->inputActive) {
			bool result = (*i)->mousePressed(arg, id);
			if(!result){
		    return false;
			}
		}
	}
	return true;
}

bool InputManager::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id ) {
	std::list<InputObserver*>::iterator i;
	for(i=m_observers->begin(); i != m_observers->end(); ++i) {
		if ((*i)->inputActive) {
			bool result = (*i)->mouseReleased(arg, id);
			if(!result){
		    return false;
			}
		}
	}
	return true;
}

void InputManager::initialize(Ogre::RenderWindow* window) {
  m_window = window;
  //Create parameter list
  OIS::ParamList pl;
  size_t windowHnd = 0;
  std::ostringstream windowHndStr;

  m_window->getCustomAttribute("WINDOW", &windowHnd);
  windowHndStr << windowHnd;
  pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
  //Create input manager from parameterlist
  m_inputManager = OIS::InputManager::createInputSystem( pl );
  //Create keyboard and mouse
  m_keyboard = static_cast<OIS::Keyboard*>(m_inputManager->createInputObject( OIS::OISKeyboard, true ));
  m_mouse = static_cast<OIS::Mouse*>(m_inputManager->createInputObject( OIS::OISMouse, true ));

  m_mouse->setEventCallback(this);
  m_keyboard->setEventCallback(this);
  //Update window size
  windowResized(m_window);

  Ogre::WindowEventUtilities::addWindowEventListener(m_window, this);
}

void InputManager::windowResized(Ogre::RenderWindow* rw) {
    unsigned int width, height, depth;
    int left, top;
    rw->getMetrics(width, height, depth, left, top);

    const OIS::MouseState &ms = m_mouse->getMouseState();
    ms.width = width;
    ms.height = height;
}

void InputManager::windowClosed(Ogre::RenderWindow* rw) {
    //Only close for window that created OIS
    if( rw == m_window ) {
        if( m_inputManager ) {
            m_inputManager->destroyInputObject( m_mouse );
            m_inputManager->destroyInputObject( m_keyboard );

            OIS::InputManager::destroyInputSystem(m_inputManager);
            m_inputManager = 0;
        }
    }
}
	
	